﻿using JESAI.DistributedLock.Internal;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace JESAI.DistributedLock.Redis;

/// <summary>
/// 充当<see cref="Task.Delay(TimeSpan, CancellationToken)"/> ，当<see cref="TimeoutTask"/>被丢弃
/// </summary>
internal readonly struct TimeoutTask : IDisposable
{
    private readonly CancellationTokenSource _cleanupTokenSource;
    private readonly CancellationTokenSource? _linkedTokenSource;

    public TimeoutTask(TimeoutValue timeout, CancellationToken cancellationToken)
    {
        this._cleanupTokenSource = new CancellationTokenSource();
        this._linkedTokenSource = cancellationToken.CanBeCanceled
            ? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, this._cleanupTokenSource.Token)
            : null;
        this.Task = Task.Delay(timeout.TimeSpan, this._linkedTokenSource?.Token ?? this._cleanupTokenSource.Token);
    }

    public Task Task { get; }

    public void Dispose()
    {
        try { this._cleanupTokenSource.Cancel(); }
        finally
        {
            this._linkedTokenSource?.Dispose();
            this._cleanupTokenSource.Dispose();
        }
    }
}
